home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / SYQUEST / SQHDX / HDX.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  24.1 KB  |  1,080 lines

  1. /* hdx.c */
  2.  
  3. /*
  4.  * Atari Hard Disk Installation Utility
  5.  * Copyright 1988 Atari Corp.
  6.  *
  7.  * Associated files
  8.  *    hdx.rsc        resource file
  9.  *    wincap        hard disk database (text file)
  10.  *
  11.  *    hdx.h        object tree definitions
  12.  *    defs.h        constant definitions
  13.  *    part.h        structure definitions
  14.  *
  15.  *    hdx.c        top level, user interface (this file)
  16.  *    epart.c        edit partition sizes
  17.  *    fmt.c        disk formatting
  18.  *    part.c        partition reading/writing
  19.  *    sect.c        sector reading, writing, zeroing
  20.  *    string.c    string functions (matching, concat, ...)
  21.  *    assist.c    markbad(), zero()
  22.  *    wincap.c    hard disk parameter / partition size database
  23.  *    st.c        random ST functions (delay, reboot, ...)
  24.  *
  25.  *----
  26.  * 11-May-1988    ml.    Cleaned up the memory management in the program
  27.  *            (ie. for all files).  Memory chunks which are for
  28.  *            sure will be < 32k is allocated using malloc(),
  29.  *            whereas chunks >= 32k is allocated using Malloc().
  30.  *            When using malloc(), you will get the 'Stack Over-
  31.  *            flow message if you are in Supervisor mode and 
  32.  *            you have your own supervisor stack.  To get around
  33.  *            this, have to use mymalloc() (in mymalloc.s).
  34.  * 15-Mar-1988    ml.    Changed interface to Markbad.
  35.  * 11-Jan-1988    ml.    Modified dialogue boxes.
  36.  * 07-Dec-1987    ml.    Started to add in concept of Bad Sector List.
  37.  * ??-Oct-1987  ml.    Partition and Disk type menu now has 15 entries 
  38.  *            instead of 16.
  39.  * 30-Sep-1987    ml.    Inherited 'this' from Landon Dyer.
  40.  * 24-Mar-1986 lmd    Released to software test.
  41.  * 15-Mar-1986 lmd    Hacked up from earlier version by Jim Tittsler.
  42.  *
  43.  */
  44.  
  45. #include "obdefs.h"
  46. #include "gemdefs.h"
  47. #include "osbind.h"
  48. #include "defs.h"
  49. #include "part.h"
  50. #include "bsl.h"
  51. #include "hdx.h"
  52. #include "addr.h"
  53. #include "error.h"
  54.  
  55.  
  56. /* Globals */
  57. int rebootp = 0;    /* 1: must reboot (not return to desktop) */
  58. int format;        /* TRUE: just formatted disk */
  59. int running;        /* 1: continue evnt_multi() loop */
  60. char sbuf[512];        /* error message buffer */
  61.  
  62. long ostack;                /* old stack pointer */
  63.  
  64. extern long bslsiz;
  65. extern BYTE *bsl;
  66.  
  67. /*  Logical-to-dev+partition mapping table. */
  68. extern int nlogdevs;        /* #logical devs found */
  69. extern LOGMAP logmap[];        /* logical dev map */
  70. extern int livedevs[];        /* live physical dev flag */
  71.  
  72. /* Partition related variables */
  73. long maxpsiz = MAXPSIZ;    /* maximum partition size */
  74.  
  75. /* AES (windows and messages) related variables */
  76. int gl_hchar;        /* height of system font (pixels) */
  77. int gl_wchar;        /* width of system font (pixels) */
  78. int gl_wbox;        /* width of box able to hold system font */
  79. int gl_hbox;        /* height of box able to hold system font */
  80.  
  81. int phys_handle;    /* physical workstation handle */
  82. int handle;        /* virtual workstation handle */
  83. int wi_handle;        /* window handle */
  84.  
  85. int formw, formh, sx, sy, lx, ly;    /* dialogue box dimensions */
  86. int xdesk, ydesk, hdesk, wdesk;        /* window X, Y, width, height */
  87. int xwork, ywork, hwork, wwork;        /* desktop and work areas */
  88.  
  89. int msgbuff[8];        /* event message buffer */
  90. int keycode;        /* keycode returned by event-keyboard */
  91. int mx, my;        /* mouse x and y pos. */
  92. int butdown;        /* button state tested for, UP/DOWN */
  93. int ret;        /* dummy return variable */
  94.  
  95. int hidden;        /* current state of cursor */
  96.  
  97. int contrl[12];
  98. int intin[128];
  99. int ptsin[128];
  100. int intout[128];
  101. int ptsout[128];    /* storage wasted for idiotic bindings */
  102.  
  103. int work_in[11];    /* Input to GSX parameter array */
  104. int work_out[57];    /* Output from GSX parameter array */
  105. int pxyarray[10];    /* input point array */
  106.  
  107.  
  108.  
  109. /*
  110.  * Top level;
  111.  * we get control from the desktop.
  112.  */
  113. main()
  114. {
  115.     running = TRUE;
  116.     appl_init();
  117.     phys_handle=graf_handle(&gl_wchar, &gl_hchar, &gl_wbox, &gl_hbox);
  118.     wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
  119.     open_vwork();
  120.     wi_handle=wind_create(WI_KIND, xdesk, ydesk, wdesk, hdesk);
  121.  
  122.     hidden = FALSE;
  123.     butdown = TRUE;
  124.  
  125.     if (!rsrc_load(RESOURCEFILE)) {
  126.     errs("[2][|", RESOURCEFILE, "][ EXIT ]");
  127.     goto punt;
  128.     }
  129.     
  130.     /* Get all addresses of dialogues from resource file */
  131.     if (getalladdr() != OK) {
  132.     errs("[2][|", RESOURCEFILE, "][ EXIT ]");
  133.     goto punt;
  134.     }
  135.  
  136.     /*
  137.      * Get maximum partition size from
  138.      * wincap "@@" entry.
  139.      */
  140.     if (wgetent("Parameters", "@@") == OK) {
  141.     if (wgetnum("ms", &maxpsiz) != OK)
  142.         maxpsiz = MAXPSIZ;
  143.     } else {
  144.         goto punt;
  145.     }
  146.  
  147.     ARROW_MOUSE;
  148.  
  149.     /* display menu bar */
  150.     menu_bar(menuobj, 1);
  151.  
  152.     while (running) {
  153.         domulti();
  154.     }
  155.  
  156.     /*
  157.      * If nothing has been done to the hard disks
  158.      * then just get out, back to the desktop.
  159.      * Otherwise reboot the system.
  160.      */
  161.     menu_bar(menuobj, 0);        /* erase menu bar */
  162.  
  163. punt:
  164.     /*
  165.      * If we have to reboot,
  166.      * tell the user and then do it.
  167.      *
  168.      */
  169.     if (rebootp) {
  170.     err(autoboot);
  171.     reboot();
  172.     }
  173.  
  174.     wind_delete(wi_handle);
  175.     v_clsvwk(handle);
  176.     appl_exit();
  177. }
  178.  
  179.  
  180. /*
  181.  * Get a single event, process it, and return.
  182.  *
  183.  */
  184. domulti(){
  185.     int event;
  186.     
  187.     event = evnt_multi(MU_MESAG,
  188.             1,1,butdown,
  189.             0,0,0,0,0,
  190.             0,0,0,0,0,
  191.             msgbuff,0,0,&mx,&my,&ret,&ret,&keycode,&ret);
  192.  
  193.     if (event & MU_MESAG) {
  194.         wind_update(TRUE);
  195.     switch (msgbuff[0]) {
  196.         case WM_REDRAW:
  197.         do_redraw(msgbuff[4],msgbuff[5],msgbuff[6],msgbuff[7]);
  198.         break;
  199.  
  200.         case MN_SELECTED:
  201.             BEE_MOUSE;
  202.         switch(msgbuff[3]) {
  203.             case MNDISK:
  204.                 rescan(0);    /* don't report medium changed */
  205.             switch (msgbuff[4]) {
  206.                 case DIFORM:
  207.                     format = TRUE;
  208.                     dodiform();
  209.                     format = FALSE;
  210.                     break;
  211.                 case DIPART:
  212.                     dodipart(-1, NULL, NULL);
  213.                     break;
  214.                 case DIZERO:
  215.                     dodizero();
  216.                     break;
  217.                 case DIMARK:
  218.                     dodimark();
  219.                     break;
  220.                 case DISHIP:
  221.                     dodiship();
  222.                     break;
  223.                 default:        break;
  224.             }
  225.             break;
  226.  
  227.             case MNFILE:
  228.             switch (msgbuff[4]) {
  229.                 case FIQUIT:
  230.                 running = 0;
  231.                 break;
  232.  
  233.                 default:
  234.                 break;
  235.             }
  236.             break;
  237.             
  238.             case MNDESK:
  239.             if(msgbuff[4] == DEABOUT) {
  240.                 strcpy(abtdial[ABVERSN].ob_spec, "Version 3.0a");
  241.                 abtdial[ABOK].ob_state = NORMAL;
  242.                 execform(abtdial);
  243.             }
  244.             break;        /* "cannot happen" */
  245.         }
  246.  
  247.         menu_tnormal(menuobj, msgbuff[3], 1);    /* back to normal */
  248.             ARROW_MOUSE;
  249.         break;
  250.         
  251.         case WM_NEWTOP:
  252.         case WM_TOPPED:
  253.         wind_set(wi_handle, WF_TOP, 0, 0, 0, 0);
  254.         break;
  255.  
  256.         case WM_CLOSED:
  257.         running = FALSE;
  258.         break;
  259.  
  260.         default:
  261.         break;
  262.     }
  263.     wind_update(FALSE);
  264.     }
  265. }
  266.  
  267.  
  268. /*
  269.  * Default partition name (no "pt" entry).
  270.  */
  271. #define    DEF_PARTNAME    "4-6-10"
  272.  
  273.  
  274. /*
  275.  * Map from button in format dial.
  276.  */
  277. int pfmt[] = {
  278.     PFMT0, PFMT1, PFMT2, PFMT3,
  279.     PFMT4, PFMT5, PFMT6, PFMT7,
  280.     PFMT8, PFMT9, PFMT10, PFMT11,
  281.     PFMT12, PFMT13, PFMT14
  282. };
  283.  
  284.  
  285. /*
  286.  * Handle [FORMAT] item.
  287.  *
  288.  */
  289. dodiform()
  290. {
  291.   extern long get3bytes();
  292.   extern char bootstop;
  293.   extern char bootend;
  294.   int dev, v, i;
  295.   int modesel;            /* flag for mode select */
  296.   long cnt, hdsiz;
  297.   char *s, *d, *wgetstr();
  298.   char bs[512], sendata[16];
  299.   char pnam[128];
  300.   char *seldev = "X";
  301.   HINFO hinfo;
  302.   char devnames[NAMSIZ];    /* device type name buffer */
  303.   long nbad;
  304.   extern long gbslsiz(), nument(), dsmarkbad();
  305.   long pattern, temp;
  306.   long longrandom();
  307.   char pr_id[2];    /* partition scheme id */
  308.   
  309.   /*
  310.    * Throw up generic formatting/partition warning,
  311.    * then get physical dev they want to clobber.
  312.    */
  313.   fwarning[FWARNCN].ob_state = NORMAL;
  314.   fwarning[FWARNOK].ob_state = NORMAL;
  315.   if (execform(fwarning) != FWARNOK) return BAILOUT;
  316.  
  317.   if ((dev = gphysdev()) < 0) {
  318.       return BAILOUT;
  319.   }
  320.   
  321.   /* Get all available disk types from wincap 'mn' entries */  
  322.   wallents(devnames, "mn");
  323.   
  324.   /* Shove format name text into buttons */
  325.   for (i = 0, s = devnames; i < 15 && *s; ++i) {
  326.       dsknames[pfmt[i]].ob_type = G_BUTTON;    /* invisible box */
  327.       dsknames[pfmt[i]].ob_spec = (long)s;
  328.       dsknames[pfmt[i]].ob_state = NORMAL;
  329.       dsknames[pfmt[i]].ob_flags = SELECTABLE | RBUTTON;
  330.       while (*s++)
  331.     ;
  332.   }
  333.   
  334.   /* rest of buttons are invisible and untouchable */
  335.   for (; i < 15; ++i) {
  336.       dsknames[pfmt[i]].ob_type = G_IBOX;    /* invisible box */
  337.       dsknames[pfmt[i]].ob_spec = 0;        /* no thickness */
  338.       dsknames[pfmt[i]].ob_state = DISABLED;    /* nobody home */
  339.       dsknames[pfmt[i]].ob_flags = NONE;        /* disabled */
  340.   }
  341.   
  342.   /* clean up rest of the form and throw it up */
  343.   dsknames[PFOK].ob_state = NORMAL;
  344.   dsknames[PFCN].ob_state = NORMAL;
  345.   if (execform(dsknames) != PFOK)
  346.     return BAILOUT;
  347.   
  348.   /* search for format they picked */
  349.   for (i = 0; i < 15; ++i)
  350.     if (dsknames[pfmt[i]].ob_state & SELECTED)
  351.       break;
  352.   if (i >= 15) {        /* nothing picked */
  353.       return BAILOUT;
  354.   }
  355.   
  356.   modesel = 1;
  357.   if (gfparm(&modesel, &hinfo, dsknames[pfmt[i]].ob_spec) != 0) {
  358.       return ERROR;
  359.   }
  360.   
  361.   /* get data pattern to test the disk */
  362.   if (wgetnum("dp", &pattern) != OK) {
  363.       pattern = longrandom();  /* can't find pattern from wincap, make one */
  364.   } else {
  365.       temp = pattern;
  366.       pattern <<= 16;    /* shift pattern to hi word */
  367.       pattern |= temp;
  368.   }
  369.   
  370.   /*
  371.    * One last chance to bail out.
  372.    */
  373.   *seldev = dev + '0';
  374.   (fmtfnl[FUNIT].ob_spec)->te_ptext = seldev;
  375.   fmtfnl[FMTYES].ob_state = NORMAL;
  376.   fmtfnl[FMTNO].ob_state = NORMAL;
  377.   if (execform(fmtfnl) != FMTYES) return BAILOUT;
  378.  
  379.   /* For REAL !! */  
  380.   dsplymsg(fmtmsg);
  381.  
  382.   bsl = 0L;
  383.   
  384.   /* Get size of Bad Sector List */
  385.   if ((bslsiz = gbslsiz(dev)) > 0L) {
  386.       /* Allocate memory for existing BSL */
  387.       if ((bsl = (BYTE *)mymalloc((int)bslsiz*512)) <= 0) {
  388.           ret = err(nomemory);
  389.           goto formend;
  390.       }
  391.       
  392.       /* Read in BSL */
  393.       if ((ret = rdbsl(dev)) != OK) {
  394.           /* Create a new BSL if current one is unusable */
  395.       if (creabsl(dev, NEW, 0L) != OK) {
  396.           ret = ERROR;
  397.           goto formend;
  398.       }
  399.       } else {
  400.             /* Remove USER BSL */
  401.             if (creabsl(dev, EXPAND, nument(VENDOR)) != OK) {
  402.                 ret = ERROR;
  403.                 goto formend;
  404.             }
  405.       }
  406.   } else if (bslsiz == 0L || bslsiz == ERROR) {    /* no bsl or read error */
  407.       if (creabsl(dev, NEW, 0L) != OK) {
  408.           ret = ERROR;
  409.           goto formend;
  410.       }
  411.   } else {    /* bslsiz == MDMERR; medium changed error */
  412.       ret = ERROR;
  413.       goto formend;
  414.   }
  415.   
  416.   /*
  417.    * In supervisor mode
  418.    * set disk format parameters
  419.    * and format the disk.
  420.    */
  421.   ostack = Super(NULL);
  422.   ret = md_sense(dev, sendata);
  423.   v = OK;                    /* assume everything is OK */
  424.   if (modesel)
  425.       v = ms(dev, &hinfo);            /* mode set */
  426.   /*
  427.   delay();                    /* kludge delay */
  428.   if (v == OK)
  429.     v = doformat(dev, (UWORD)hinfo.hi_in);  /* format /**/
  430.   delay();                    /* kludge delay */
  431.   Super(ostack);
  432.   
  433.   if (v != 0) {
  434.       ret = errcode(dev);
  435.       if (tsterr(ret) != OK)
  436.           formaterr(dev);
  437.       ret = ERROR;
  438.       goto formend;
  439.   }
  440.   
  441.   /* Find formatted capacity of drive */
  442.   if (modesel) {
  443.       hdsiz = (long)hinfo.hi_cc * (long)hinfo.hi_dhc * (long)hinfo.hi_spt;
  444.   } else {
  445.       /* Do a mode sense to find out size of disk */
  446.       ostack = Super(NULL);
  447.       ret = md_sense(dev, sendata);
  448.       delay();
  449.       Super(ostack);
  450.       if (ret != 0) {
  451.           ret = formaterr(dev);
  452.           goto formend;
  453.       }
  454.       hdsiz = get3bytes(sendata+5);
  455.   }
  456.   
  457.   ret = OK;
  458.   rebootp = 1;
  459. formend:
  460.   erasemsg();    /* Erase formatting box */
  461.   if (ret < 0) {
  462.       if (bsl > 0) free(bsl);
  463.       return ERROR;
  464.   }
  465.   
  466.   /*------------------------------------------*
  467.    * Markbad the device destructively.          *
  468.    * Bad Sectors found are added to the BSL.  *
  469.    * Write BSL to device.              *
  470.    *------------------------------------------*/
  471.   if ((nbad = dsmarkbad(dev, hdsiz, 1, pattern)) < 0) {
  472.       free(bsl);
  473.       return ERROR;
  474.   }
  475.       
  476.   if (wrbsl(dev) != OK) {
  477.       free(bsl);
  478.       return ERROR;
  479.   }
  480.   free(bsl);
  481.  
  482.     
  483.   /*
  484.    * Install boot-stopper in sector image;
  485.    * write root sector to device.
  486.    * 6-13-88  Setting of soft format parameters in root sector sets
  487.    *        the hard disk size only.
  488.    */
  489.   fillbuf(bs, 512L, 0L);    /* create new root sector */
  490.   sbslparm(bs);            /* set BSL parameters */
  491.   sfmtparm(bs, hdsiz);
  492.   for (d = bs, s = &bootstop, cnt = &bootend - &bootstop; --cnt;)
  493.     *d++ = *s++;
  494.   Protobt(bs, -1L, -1, 1);    /* make root sector executable */
  495.   
  496.   if ((ret = putroot(dev, bs)) != OK) {
  497.       if (tsterr(ret) != OK)
  498.       err(rootwrit);
  499.       return ERROR;
  500.   }
  501.  
  502.   /*
  503.    * Make a copy of the default partition name.
  504.    * Figure out the partition scheme id.
  505.    */
  506.   if ((s = wgetstr("pt")) == NULL)
  507.     s = DEF_PARTNAME;
  508.   strcpy(pnam, s);
  509.   figprid(((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz, pr_id);
  510.   dodipart(dev, pnam, pr_id);
  511.   return OK;
  512. }
  513.  
  514.  
  515.  
  516. /*
  517.  * Handle [PARTITION] item;
  518.  * if `xdev' is -1, throw up dialog boxes;
  519.  * if `xdev' >= 0, just partition the dev,
  520.  * using `pnam' as the partition type, 
  521.  * and `pr_id' to search for the type.
  522.  *
  523.  */
  524. dodipart(xdev, pnam, pr_id)
  525. int xdev;
  526. char *pnam;
  527. char *pr_id;
  528. {
  529.     int dev, i, ret =OK, fine;
  530.     char *seldev = "X";
  531.     char *s;
  532.     char bs[512];
  533.     PART pinfo[4];
  534.     extern long gbslsiz();
  535.  
  536.     if (xdev < 0) {
  537.     /*
  538.      * Throw up warning saying that partition is dangerous;
  539.      * then get physical dev they want to clobber.
  540.      */
  541.     pwarning[PWARNCN].ob_state = NORMAL;
  542.     pwarning[PWARNOK].ob_state = NORMAL;
  543.     if (execform(pwarning) != PWARNOK) return BAILOUT;
  544.     format = FALSE;
  545.     if ((dev = gphysdev()) < 0) {
  546.         return BAILOUT;
  547.     }
  548.  
  549.     /*
  550.      * Let the user edit/pick partitions.
  551.      */
  552.     fine = 0;
  553.     while (!fine) {
  554.         if (figpart(dev, pinfo) != OK)
  555.             return BAILOUT;
  556.         if ((ret = chkpart(dev, pinfo)) != OK) {
  557.             if (ret < 0)
  558.                 err(nexsmem);
  559.             else return BAILOUT;
  560.         } else {
  561.             fine = 1;
  562.         }
  563.     }
  564.  
  565.     /* Last chance to bail out */
  566.     *seldev = dev + '0';
  567.     (partfnl[PUNIT].ob_spec)->te_ptext = seldev;
  568.     partfnl[PARTYES].ob_state = NORMAL;
  569.     partfnl[PARTNO].ob_state = NORMAL;
  570.     if (execform(partfnl) != PARTYES)
  571.         return BAILOUT;
  572.  
  573.     } else {
  574.     if (wgetent(pnam, pr_id) != OK) {
  575.         nopart[NOSCHPOK].ob_state = NORMAL;
  576.         (nopart[NOSCHPR].ob_spec)->te_ptext = pnam;
  577.         execform(nopart);
  578.         return ERROR;
  579.     }
  580.  
  581.     dev = xdev;
  582.     for (i = 0; i < 4; ++i)
  583.         fillpart(i, &pinfo[i]);
  584.     }
  585.  
  586.     /* For REAL!! */
  587.     dsplymsg(partmsg);
  588.     
  589.     bsl = 0L;
  590.     
  591.     /* Get size of BSL */
  592.     if ((bslsiz = gbslsiz(dev)) > 0L) {
  593.         /* Allocate memory for existing BSL */
  594.         if ((bsl = (BYTE *)mymalloc((int)bslsiz*512)) <= 0) {
  595.             ret = err(nomemory);
  596.             goto partend;
  597.         }
  598.             
  599.         /* Read in BSL */
  600.         if ((ret = rdbsl(dev)) != OK) {
  601.             if (ret == INVALID)
  602.                 err(cruptbsl);
  603.             ret = ERROR;
  604.             goto partend;
  605.         }
  606.     } else if (bslsiz == 0) {
  607.         ret = err(oldfmt);
  608.     goto partend;
  609.     } else if (bslsiz == ERROR) {
  610.         ret = err(rootread);
  611.         goto partend;
  612.     }
  613.     
  614.     /* Lay out partition headers */
  615.     if (pheader(dev, &pinfo[0]) != OK) {
  616.         ret = ERROR;
  617.         goto partend;
  618.     }
  619.     
  620.     if (wrbsl(dev) != OK) {        /* write BSL */
  621.         ret = ERROR;
  622.         goto partend;
  623.     }
  624.     
  625.     /*
  626.      * Shove partition parms into root sector.
  627.      */
  628.     if ((ret = getroot(dev, bs)) != 0) {
  629.         if (tsterr(ret) != OK)
  630.         err(rootread);
  631.     ret = ERROR;
  632.     goto partend;
  633.     }
  634.  
  635.     spart(bs, &pinfo[0]);        /* set partition parameters */
  636.     sbslparm(bs);            /* set bsl parameters */
  637.     Protobt(bs, -1L, -1, 1);        /* make root sector executable */
  638.     if ((ret = putroot(dev, bs)) != OK) {
  639.         if (tsterr(ret) != OK)
  640.             err(rootwrit);
  641.         ret = ERROR;
  642.         goto partend;
  643.     }
  644.  
  645.     if (rescan(1)) {        /* has to be here because map changed    */
  646.         ret = ERROR;        /* after partitions are moved around,    */
  647.         goto partend;        /* report medium change error.        */
  648.     }
  649.     
  650.     /* Partition the device with parameters given in pinfo */
  651.     if (dopart(dev, &pinfo[0]) != OK)
  652.         ret = ERROR;
  653.     else
  654.         ret = OK;
  655.         
  656.     rebootp = 1;
  657. partend:
  658.     if (bsl > 0) free(bsl);
  659.     erasemsg();
  660.     return (ret);
  661. }
  662.  
  663.  
  664.  
  665. /*
  666.  * Handle [ZERO] item.
  667.  *
  668.  */
  669. dodizero()
  670. {
  671.     int ldev, ret;
  672.     char *seldev = "X";
  673.     int i; 
  674.  
  675.     zwarning[ZWOK].ob_state = NORMAL;
  676.     zwarning[ZWCN].ob_state = NORMAL;
  677.     if (execform(zwarning) != ZWOK)
  678.     return BAILOUT;
  679.  
  680.     if ((ldev = glogdev()) < 0) return BAILOUT;
  681.  
  682.     /* Find out if logical device has assumed parameters */
  683.     if (chkparm(ldev) != OK) {
  684.         wronparm[WRONOK].ob_state = NORMAL;
  685.     execform(wronparm);
  686.     return ERROR;
  687.     }
  688.         
  689.     *seldev = ldev;
  690.     (zerofnl[ZDRV].ob_spec)->te_ptext = seldev;
  691.     strcat((zerofnl[ZDRV].ob_spec)->te_ptext, ":");
  692.     zerofnl[ZYES].ob_state = NORMAL;
  693.     zerofnl[ZNO].ob_state = NORMAL;
  694.     if (execform(zerofnl) != ZYES)  return BAILOUT;
  695.  
  696.     dsplymsg(zeromsg);
  697.     if (zero(ldev) == OK) {
  698.     if (!rebootp) {
  699.         for (i = 0; i < 10; i++) {
  700.         if (!mediach(ldev-'A')) break;
  701.         }
  702.         if (i == 10) {
  703.             rebootp = 1;
  704.         err(mdach);
  705.             }
  706.     }
  707.     }
  708.     erasemsg();
  709. }
  710.  
  711.  
  712. /*
  713.  * Handle [MARKBAD] item.
  714.  *
  715.  */
  716. dodimark()
  717. {
  718.     int ldev, ret;
  719.     int i;
  720.  
  721.     mwarning[MWARNOK].ob_state = NORMAL;
  722.     mwarning[MWARNCN].ob_state = NORMAL;
  723.     if (execform(mwarning) == MWARNCN)
  724.         return BAILOUT;
  725.     if ((ldev = glogdev()) < 0)
  726.         return BAILOUT;
  727.         
  728.     /* Find out if logical device has assumed parameters */
  729.     if (chkparm(ldev) != OK) {
  730.         wronparm[WRONOK].ob_state = NORMAL;
  731.     execform(wronparm);
  732.     return ERROR;
  733.     }
  734.          
  735.     dsplymsg(lmrkmsg);
  736.     if (markbad(ldev) != OK) {
  737.         erasemsg();
  738.     } else {
  739.         if (!rebootp) {
  740.         for (i = 0; i < 10; i++) {
  741.         if (!mediach(ldev-'A')) break;
  742.         }
  743.         if (i == 10) {
  744.             rebootp = 1;
  745.         err(mdach);
  746.             }
  747.         }
  748.     }
  749. }
  750.  
  751.  
  752. /*
  753.  * Map from button in ship dial.
  754.  */
  755. int sdev[] = {
  756.     SDEV0, SDEV1, SDEV2, SDEV3,
  757.     SDEV4, SDEV5, SDEV6, SDEV7
  758. };
  759.  
  760. /*
  761.  * Ship selected devices.
  762.  */
  763. dodiship()
  764. {
  765.   int i, seldev[8], selected=0;
  766.   
  767.     
  768.   /* Throw up generic shipping warning. */
  769.   shipdial[SWARNCN].ob_state = NORMAL;
  770.   shipdial[SWARNOK].ob_state = NORMAL;
  771.   if (execform(shipdial) != SWARNOK) return BAILOUT;
  772.   
  773.   /* Device(s) selected? */
  774.   shipdev[SDEVOK].ob_state = NORMAL;
  775.   shipdev[SDEVCN].ob_state = NORMAL;
  776.   for(i = 0; i < MAXPHYSDEVS; i++) {        /* indicate what's alive */
  777.       if (livedevs[i] == 0)
  778.       shipdev[sdev[i]].ob_state = NORMAL;
  779.       else
  780.         shipdev[sdev[i]].ob_state = NORMAL | SHADOWED;
  781.   }
  782.   
  783.   if (execform(shipdev) != SDEVOK)
  784.       return BAILOUT;
  785.       
  786.   for(i = 0; i < MAXPHYSDEVS; i++) {    /* search for selected unit */
  787.       if (shipdev[sdev[i]].ob_state & SELECTED) {
  788.           seldev[i] = 1;
  789.           selected++;
  790.       } else {
  791.             seldev[i] = 0;
  792.       }
  793.   }
  794.   
  795.   if (!selected) return BAILOUT;    /* nothing is selected */
  796.   
  797.   /* Throw up final shipping warning. */
  798.   shipfnl[SFNLCN].ob_state = NORMAL;
  799.   shipfnl[SFNLOK].ob_state = NORMAL;
  800.   if (execform(shipfnl) != SFNLOK) return BAILOUT;
  801.   
  802.   /* For REAL!!! */
  803.   /* Ship selected devices */
  804.   for (i = 0; i < MAXPHYSDEV; i++) {
  805.       if (seldev[i])
  806.           ship(i);
  807.   }
  808.   
  809.   /* Put out final message about turning off hard disks */
  810.   scommand[TRNOFFOK].ob_state = NORMAL;
  811.   execform(scommand);
  812. }
  813.  
  814.  
  815.  
  816. /*
  817.  * Translate unit number to tree index.
  818.  *
  819.  */
  820. static int physxlat[] = {
  821.     UNIT0, UNIT1, UNIT2, UNIT3,
  822.     UNIT4, UNIT5, UNIT6, UNIT7
  823. };
  824.  
  825.  
  826. /*
  827.  * Get physical device#,
  828.  * return devno or -1.
  829.  *
  830.  */
  831. gphysdev()
  832. {
  833.     int i, start;
  834.  
  835.     /*
  836.      * Clean up and exec object;
  837.      * shadow devs we KNOW are there.
  838.      */
  839.     physdial[PHYSOK].ob_state = NORMAL;
  840.     physdial[PHYSCN].ob_state = NORMAL;
  841.     
  842.     if (format == TRUE) {
  843.         start = 1;        /* start initializing at unit 0 */
  844.     physdial[physxlat[0]].ob_state = NORMAL;
  845.     } else {
  846.         start = 0;        /* start initializing at unit 1 */
  847.     }
  848.     
  849.     for (i = start; i < MAXPHYSDEVS; ++i)
  850.     physdial[physxlat[i]].ob_state = DISABLED;
  851.     for (i = 0; i < MAXPHYSDEVS; ++i)
  852.     if (livedevs[i])
  853.         physdial[physxlat[i]].ob_state = NORMAL | SHADOWED;
  854.  
  855.     if (execform(physdial) != PHYSOK)
  856.     return ERROR;
  857.      
  858.     /* search for selected unit */
  859.     for (i = 0; i < MAXPHYSDEVS; ++i)
  860.     if (physdial[physxlat[i]].ob_state & SELECTED)
  861.         return i;
  862.  
  863.     return ERROR;            /* if no object selected */
  864. }
  865.  
  866.  
  867. /*
  868.  * Translate from logical device number
  869.  * to object number in logical device
  870.  * dialouge box.
  871.  */
  872. int logxlat[] = {
  873.     CCOLON, DCOLON, ECOLON, FCOLON,
  874.     GCOLON, HCOLON, ICOLON, JCOLON,
  875.     KCOLON, LCOLON, MCOLON, NCOLON,
  876.     OCOLON, PCOLON
  877. };
  878.  
  879.  
  880. /*
  881.  * Get logical device,
  882.  * return 'C'...'P'
  883.  * or -1.
  884.  *
  885.  */
  886. glogdev()
  887. {
  888.     int i, flg;
  889.  
  890.     /*
  891.      * Setup tree; selectively enable drive buttons
  892.      * and so on.
  893.      */
  894.     logdial[LOGOK].ob_state = NORMAL;
  895.     logdial[LOGCN].ob_state = NORMAL;
  896.     for (i = 0; i < MAXLOGDEVS; ++i) {
  897.     if (logmap[i].lm_physdev < 0)
  898.         flg = DISABLED;
  899.         else flg = NORMAL;
  900.     logdial[logxlat[i]].ob_state = flg;
  901.     }
  902.  
  903.     if (execform(logdial) != LOGOK) return -1;
  904.  
  905.     for (i = 0; i < MAXLOGDEVS; ++i)
  906.     if (logdial[logxlat[i]].ob_state & SELECTED)
  907.         return i + 'C';
  908.  
  909.     return -1;
  910. }
  911.  
  912.  
  913. /*
  914.  * Open virtual workstation.
  915.  *
  916.  */
  917. open_vwork()
  918. {
  919.     int i;
  920.  
  921.     for (i = 0; i < 10;)
  922.     work_in[i++] = 1;
  923.     work_in[10] = 2;
  924.     handle = phys_handle;
  925.     v_opnvwk(work_in, &handle, work_out);
  926. }
  927.  
  928.  
  929. /*
  930.  * Find and redraw all clipping rectangles
  931.  *
  932.  */
  933. do_redraw(xc, yc, wc, hc)
  934. int xc, yc, wc, hc;
  935. {
  936.     GRECT t1, t2;
  937.     int temp[4];
  938.  
  939.     hide_mouse();
  940.     t2.g_x=xc;
  941.     t2.g_y=yc;
  942.     t2.g_w=wc;
  943.     t2.g_h=hc;
  944.     vsf_interior(handle, 1);
  945.     vsf_color(handle, 0);
  946.     wind_get(wi_handle, WF_FIRSTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  947.     while (t1.g_w && t1.g_h) {
  948.     if (rc_intersect(&t2, &t1)) {
  949.         set_clip(t1.g_x, t1.g_y, t1.g_w, t1.g_h);
  950.         temp[0] = xwork;
  951.         temp[1] = ywork;
  952.         temp[2] = xwork + wwork - 1;
  953.         temp[3] = ywork + hwork - 1;
  954.         v_bar(handle, temp);
  955.     }
  956.     wind_get(wi_handle, WF_NEXTXYWH, &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  957.     }
  958.  
  959.     show_mouse();
  960. }
  961.  
  962.  
  963. /*
  964.  * Hide the mouse.
  965.  *
  966.  */
  967. hide_mouse()
  968. {
  969.     if (!hidden) {
  970.     graf_mouse(M_OFF, 0L);
  971.     hidden = TRUE;
  972.     }
  973. }
  974.  
  975.  
  976. /*
  977.  * Show the mouse.
  978.  *
  979.  */
  980. show_mouse() 
  981. {
  982.     if (hidden) {
  983.     graf_mouse(M_ON, 0L);
  984.     hidden = FALSE;
  985.     }
  986. }
  987.  
  988.  
  989. /*
  990.  * Set clipping rectangle.
  991.  *
  992.  */
  993. set_clip(x, y, w, h)
  994. int x, y, w, h;
  995. {
  996.     int clip[4];
  997.  
  998.     clip[0] = x;
  999.     clip[1] = y;
  1000.     clip[2] = x + w;
  1001.     clip[3] = y + h;
  1002.     vs_clip(handle, 1, clip);
  1003. }
  1004.  
  1005.  
  1006. /*
  1007.  * "Execute" form,
  1008.  * return thingy that caused the exit.
  1009.  *
  1010.  */
  1011. execform(tree)
  1012. OBJECT tree[];
  1013. {
  1014.     int thingy;
  1015.  
  1016.     ARROW_MOUSE;
  1017.     dsplymsg(tree);
  1018.     thingy = form_do(tree, 0);
  1019.     erasemsg();
  1020.     BEE_MOUSE;
  1021.     return thingy;
  1022. }
  1023.  
  1024.  
  1025. /*
  1026.  *  Display a dialogue box on the screen.
  1027.  *    Input:
  1028.  *        tree - object tree for dialogue box to be displayed.
  1029.  *    Output:
  1030.  *        formw, formh, sx, sy, lx, ly - dimensions of box.
  1031.  */
  1032. dsplymsg(tree)
  1033. OBJECT tree[];
  1034. {
  1035.     formw = tree[0].ob_width;
  1036.     formh = tree[0].ob_height;
  1037.     
  1038.     sx = wdesk / 2;
  1039.     sy = hdesk / 2;
  1040.     lx = (wdesk - formw) / 2;
  1041.     ly = (hdesk - formh) / 2;
  1042.     
  1043.     tree[0].ob_x = lx;
  1044.     tree[0].ob_y = ly;
  1045.     
  1046.     form_dial(0, sx, sy, 0, 0, lx, ly, formw, formh);
  1047.     form_dial(1, sx, sy, 0, 0, lx, ly, formw, formh);
  1048.     objc_draw(tree, 0, MAX_DEPTH, 0, 0, wdesk, hdesk);
  1049. }
  1050.  
  1051.  
  1052. /*
  1053.  *  Erase a dialogue box from the screen.
  1054.  *    Input:
  1055.  *        formw, formh, sx, sy, lx, ly - dimensions of box.
  1056.  */
  1057. erasemsg()
  1058. {
  1059.     form_dial(2, sx, sy, 0, 0, lx, ly, formw, formh);
  1060.     form_dial(3, sx, sy, 0, 0, lx-3, ly-3, formw+4, formh+4);
  1061. }
  1062.  
  1063.  
  1064.  
  1065. /*
  1066.  *  Make a long (4-byte) random.
  1067.  */ 
  1068. long
  1069. longrandom()
  1070. {
  1071.     long pattern;
  1072.     
  1073.     pattern = Random();
  1074.     pattern <<= 16;
  1075.     pattern ^= Random();
  1076.     
  1077.     return (pattern);
  1078. }
  1079.  
  1080.